﻿using System;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Animation;
using MIC_GUI.Misc;
using MIC_GUI.Model;

namespace MIC_GUI
{
    /// <summary>
    /// Interaction logic for DataStreamVisualizer.xaml
    /// </summary>
    public partial class DataStreamVisualizer : UserControl
    {
        #region fields
        private double maxValue = 0;
        private double minValue = double.MaxValue;
        public bool CanAcceptNewStreamingReadings = true;
        private bool graphExpanded = false;

        #endregion

        #region Properties
        /// <summary>
        /// Gets or Sets whether graph is visible
        /// </summary>
        public bool IsGraphVisible {
            get { return graphExpanded; }
            set
            {
                if (graphExpanded)
                    PlayStoryBoard("unexpandGraph");
                else
                    PlayStoryBoard("expandGraph");
                
                graphExpanded = value;
                CanAcceptNewStreamingReadings = value;
            }
        }
        #endregion

        #region Ctor
        /// <summary>
        /// Constructor
        /// </summary>
        public DataStreamVisualizer()
        {
            InitializeComponent();
            
            
            

            maxValue = 0;
            minValue = Double.MaxValue;
        }

        

        
        /// <summary>
        /// Button event
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void btnGraph_Click(object sender, RoutedEventArgs e)
        {
            IsGraphVisible = !IsGraphVisible;
        }

        /// <summary>
        /// Plays a storyboard from xaml
        /// </summary>
        /// <param name="story">Name of storyboard</param>
        void PlayStoryBoard(string story)
        {
            BeginStoryboard((Storyboard)this.FindResource(story));
        }

        
        #endregion

        #region Public Methods

        /// <summary>
        /// Works out the actual X/Y points for the each value within the
        /// ObservableCollection<GraphDataItem> property.
        /// </summary>
        public void ObtainPointsForValues()
        {
            

            #region MinMax
            //work out min/max for Y-Scale
            
            foreach (var dataValue in DataValues)
            {
                if (dataValue.DataValue > maxValue)
                    maxValue = dataValue.DataValue;
                if (dataValue.DataValue < minValue)
                    minValue = dataValue.DataValue;
            }
            #endregion

            //Only proceed if there are some actual values
            if (DataValues != null)
            {
                #region Do Labels
                //RHS Scale : Build up all the scale labels, showing 2 decimal places
                tbMax.Text = "MAX: " + maxValue.ToString("N2");
                tbMin.Text = "MIN: " + minValue.ToString("N2");
                tbCurrentValue.Text = this.DataValues.Last().DataValue.ToString("N2");
                tbSampleRate.Text = this.DataValues.Last().TimeSampled.Milliseconds.ToString() + "ms";
                #endregion

            }
            else
            {

            }
        }



        #endregion

        #region Private Methods

        /// <summary>
        /// When the current collection of GraphDataItem changes, work out
        /// the actual X/Y point values based on the actual values
        /// </summary>
        private void DataValues_CollectionChanged(object sender, 
            System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            ObtainPointsForValues();
        }
        #endregion

        #region DPs

        #region GraphTitle

        /// <summary>
        /// GraphTitle Dependency Property
        /// </summary>
        public static readonly DependencyProperty GraphTitleProperty =
            DependencyProperty.Register("GraphTitle", typeof(String), typeof(DataStreamVisualizer),
                new FrameworkPropertyMetadata((String)String.Empty,
                    new PropertyChangedCallback(OnGraphTitleChanged)));

        /// <summary>
        /// Gets or sets the GraphTitle property.  
        /// </summary>
        public String GraphTitle
        {
            get { return (String)GetValue(GraphTitleProperty); }
            set { SetValue(GraphTitleProperty, value); }
        }

        /// <summary>
        /// Handles changes to the GraphTitle property.
        /// </summary>
        private static void OnGraphTitleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((DataStreamVisualizer)d).tbTitle.Text = (String)e.NewValue;
        }
        #endregion

        #region DataValues

        /// <summary>
        /// DataValues Dependency Property
        /// </summary>
        public static readonly DependencyProperty DataValuesProperty =
            DependencyProperty.Register("DataValues",
            typeof(ThreadSafeObservableCollection<DataItem>), typeof(DataStreamVisualizer),
                new FrameworkPropertyMetadata(
                        (ThreadSafeObservableCollection<DataItem>)null,
                    new PropertyChangedCallback(OnDataValuesChanged)));

        /// <summary>
        /// Gets or sets the DataValues property.  
        /// </summary>
        public ThreadSafeObservableCollection<DataItem> DataValues
        {
            get
            {
                return (ThreadSafeObservableCollection<DataItem>)
                    GetValue(DataValuesProperty);
            }
            set { SetValue(DataValuesProperty, value); }
        }

        /// <summary>
        /// Handles changes to the DataValues property.
        /// </summary>
        private static void OnDataValuesChanged(DependencyObject d,
            DependencyPropertyChangedEventArgs e)
        {
            DataStreamVisualizer obj = (DataStreamVisualizer)d;

            if (e.NewValue != null && e.OldValue != null)
            {
                //if we see a different actual ThreadSafeObservableCollection<GraphDataItem>
                //we should unhook the old event handler
                if (!Object.ReferenceEquals(e.OldValue, e.NewValue))
                {
                    ThreadSafeObservableCollection<DataItem> oldDataValues =
                        (ThreadSafeObservableCollection<DataItem>)e.OldValue;
                    oldDataValues.CollectionChanged -= obj.DataValues_CollectionChanged;

                    ThreadSafeObservableCollection<DataItem> newDataValues =
                        (ThreadSafeObservableCollection<DataItem>)e.OldValue;
                    newDataValues.CollectionChanged += obj.DataValues_CollectionChanged;
                }
                else
                {
                    ThreadSafeObservableCollection<DataItem> newDataValues =
                        (ThreadSafeObservableCollection<DataItem>)e.NewValue;
                    newDataValues.CollectionChanged += obj.DataValues_CollectionChanged;
                }
            }
            else
            {
                ThreadSafeObservableCollection<DataItem> newDataValues =
                    (ThreadSafeObservableCollection<DataItem>)e.NewValue;
                newDataValues.CollectionChanged += obj.DataValues_CollectionChanged;
            }

        }
        #endregion
        #endregion


    }
}
